<template>
  <div class="episode-management">
    <div class="complete-loading-content" v-if="completeLoading">
      <el-icon class="complete-loading-icon"><Loading /></el-icon>
      <p class="complete-loading-message">{{ sceneMessage || '正在加载，请稍候...' }}</p>
    </div>
    <template v-else>
      <div v-if="!hasRoles" class="empty-state">
        <img src="@/assets/images/empty.png" class="empty-image" alt="暂无角色" />
        <p class="empty-text">请先在角色生成页面点击 [角色创建] 按钮创建角色</p>
        <el-button color="#1c1d29" @click="goToRolePage">去生成</el-button>
      </div>
      <!-- 空状态：有角色但无场景 -->
      <div v-else-if="!scenes.length || !!scenes.find(item => item.status !== 'CONFIRM')" class="empty-state">
        <img src="@/assets/images/empty.png" class="empty-image" alt="暂无场景" />
        <p class="empty-text">请先在场景生成页面{{scenes.length ? ' 确认所有未确认场景' : '点击 [场景创建] 按钮创建场景'}}</p>
        <el-button color="#1c1d29" @click="goToScenePage">去{{ scenes.length ? '确认' : '生成' }}</el-button>
      </div>
      <!-- 正常剧集列表 -->
      <template v-else>
        <!-- 新增剧集按钮 -->
        <div class="episode-header">
          <el-button 
            color="#1c1d29" 
            @click="handleAddEpisode"
            class="add-episode-btn"
          >
            <el-icon class="mr-1"><Plus /></el-icon>新增剧集
          </el-button>
        </div>
        
        <el-table
          :data="episodes"
          style="width: 100%"
          border
          v-loading="loading"
        >
          <el-table-column prop="seqNo" label="分集" min-width="120">
            <template #default="{ row }">
              <span style="color:#1C1D29;font-size: 14px;">第{{row.seqNo}}集</span>
            </template>
          </el-table-column>
          
          <el-table-column label="分镜镜头" min-width="120">
            <template #default="{ row }">
              <span style="color:#1C1D29;font-size: 14px;">{{ [3, 5].includes(row.storyboardStatus) ? '拆分中...' : (row.storyboardNum || 0) }}</span>
            </template>
          </el-table-column>
          
          <el-table-column label="图片状态" min-width="120">
            <template #default="{ row }">
              <div class="status-tag-wrapper">
                <div class="status-tag" :class="getStatusClass(row.imageStatus)">
                  {{ getStatusText(row.imageStatus) }}
                </div>
              </div>
            </template>
          </el-table-column>
          
          <el-table-column label="视频状态" min-width="120">
            <template #default="{ row }">
              <div class="status-tag-wrapper">
                <div class="status-tag" :class="getStatusClass(row.videoStatus)">
                  {{ getStatusText(row.videoStatus) }}
                </div>
              </div>
            </template>
          </el-table-column>
          
          <el-table-column label="编辑时间" min-width="180">
            <template #default="{ row }">
              <span style="color:#1C1D29;font-size: 14px;">{{ formatTime(row.updateAt) }}</span>
            </template>
          </el-table-column>
          
          <el-table-column label="操作" min-width="180">
            <template #default="{ row }">
              <div class="flex items-center justify-between">
                <div class="flex space-x-2">
                  <template v-if="isGenerating(row)">
                    <span>-</span>
                  </template>
                  <template v-else-if="needsGeneration(row)">
                  <span class="txt-btn" @click="handleNavigateToStoryboard(row)">去生成</span>
                  <span v-if="![3,5].includes(row.storyboardStatus)" class="txt-btn" @click="resplit(row)">重新拆分</span>
            </template>
                  <template v-else>
                    <span class="txt-btn" @click="handleNavigateToStoryboard(row, true)">编辑</span>
                    <span class="txt-btn" @click="handleNavigateToStoryboard(row)">导出素材</span>
                  </template>
                </div>
              </div>
            </template>
          </el-table-column>
        </el-table>
        <!-- 空状态：无剧集数据 -->
        <el-empty
          v-if="!loading && episodes.length === 0"
          description="暂无剧集数据"
          class="mt-8"
        >
        </el-empty>
      </template>
    </template>
    
    <!-- 分镜弹窗 -->
    <div v-if="storyboardDialogVisible" class="storyboard-page">
      <!-- 导航栏 -->
      <div class="storyboard-header">
        <div class="storyboard-header-left">
          <el-button class="back-button" @click="storyboardDialogVisible = false">
            <el-icon><ArrowLeft /></el-icon>
          </el-button>
          <span class="episode-title">第{{currentEpisode?.seqNo || 1}}集</span>
        </div>
        
        <div class="storyboard-progress">
          <div class="progress-item" :class="{ 'active': storyboardActiveTab === 'storyboards' }">
            <div class="progress-circle">1</div>
            <div class="progress-text">确定分镜</div>
          </div>
          <div class="progress-line"></div>
          <div class="progress-item" :class="{ 'active': storyboardActiveTab === 'gallery' }">
            <div class="progress-circle">2</div>
            <div class="progress-text">图集生成</div>
          </div>
          <div class="progress-line"></div>
          <div class="progress-item" :class="{ 'active': storyboardActiveTab === 'video' }">
            <div class="progress-circle">3</div>
            <div class="progress-text">视频生成</div>
          </div>
        </div>
        
        <div class="storyboard-header-right">
          <el-button 
            color="#1c1d29" 
            @click="handleNextStep"
          >
            {{ storyboardActiveTab === 'storyboards' ? '下一步，生成分镜图集' : '下一步，生成视频' }}
          </el-button>
        </div>
      </div>
      
      <!-- 内容区 -->
      <div class="storyboard-content">
        <!-- 左侧剧本区域 -->
        <div class="script-area">
          <div class="script-title">分集剧本</div>
          <div class="script-content">等待提供数据</div>
        </div>
        
        <!-- 右侧分镜列表 -->
        <div class="storyboard-list-area">
          <div class="storyboard-list-header">
            <div class="storyboard-list-title">分镜进度</div>
            <el-button 
              color="#1c1d29" 
              @click="handleAddStoryboardItem"
              v-if="storyboardItems.length > 0"
            >
              <el-icon class="mr-1"><Plus /></el-icon>添加分镜
            </el-button>
          </div>
          
          <!-- 加载中状态 -->
          <div v-if="pollingTimer" class="loading-container">
            <div class="polling-status">
              <el-icon class="loading-icon is-loading"><Loading /></el-icon>
              <span class="loading-text">正在初始化分镜数据，请稍候...</span>
              <div class="polling-progress">
                <div class="polling-bar" :style="{ width: `${Math.min((pollingCount / maxPollingCount) * 100, 100)}%` }"></div>
              </div>
            </div>
          </div>
          
          <!-- 分镜列表 -->
          <div 
            v-if="!pollingTimer && storyboardItems.length > 0"
            class="storyboard-cards"
          >
            <div 
              v-for="(item, index) in storyboardItems" 
              :key="index"
              class="storyboard-card"
            >
              <div class="storyboard-card-header">
                <div class="storyboard-card-title">分镜 {{item.sbNo}}</div>
                <el-button 
                  class="delete-button" 
                  @click="handleDeleteStoryboardItem(index)"
                  link 
                >
                  <el-icon><Delete /></el-icon>
                </el-button>
              </div>
              
              <div class="storyboard-card-content">
                <div class="form-item">
                  <div class="form-label">镜头描述</div>
                  <el-input
                    v-model="item.sbDesc"
                    type="textarea"
                    :rows="2"
                    placeholder="请输入镜头描述"
                    @change="handleItemChange(item, index)"
                  />
                </div>
                
                <div class="form-grid">
                  <div class="form-column">
                    <div class="form-label">角色选择</div>
                    <div class="actors-list">
                      <div v-for="(actor, actorIndex) in item.actors" :key="actorIndex" class="actor-item">
                        <el-select 
                          :suffix-icon="CaretBottom"
                          v-model="actor.actorId" 
                          placeholder="请选择角色" 
                          style="width: 100%" 
                          @change="handleActorChangeInList(actor, item, index)"
                        >
                          <el-option
                            v-for="role in roles"
                            :key="role.id"
                            :label="role.actorName"
                            :value="role.actorId"
                          />
                        </el-select>
                        
                        <el-select 
                          :suffix-icon="CaretBottom"
                          v-model="actor.perspective" 
                          placeholder="请选择人物视角" 
                          style="width: 100%; margin-top: 8px;" 
                          @change="handlePerspectiveChangeInList(actor, item, index)"
                        >
                          <el-option label="主图" value="WHOLE_BODY_FRONT" />
                          <el-option label="侧图" value="WHOLE_BODY_SIDE" />
                          <el-option label="背图" value="WHOLE_BODY_BACK" />
                          <el-option label="半身图" value="HALF_BODY" />
                        </el-select>
                      </div>
                    </div>
                  </div>
                  
                  <div class="form-column">
                    <div class="form-label">场景选择</div>
                    <div class="scene-description" v-if="item.sceneId">{{item.sceneUrl}}</div>
                    <div class="scene-preview" v-if="item.scenePreviewUrl">
                      <img :src="item.scenePreviewUrl" class="scene-image" alt="场景预览" />
                    </div>
                    <div class="scene-actions">
                      <el-button 
                        type="text" 
                        @click="handleSelectScene(item, index)"
                        style="color: #3644E0; font-size: 14px;"
                      >
                        切换场景
                      </el-button>
                      <span class="divider"></span>
                      <el-button 
                        type="text" 
                        @click="handleCreateScene(item, index)"
                        style="color: #3644E0; font-size: 14px;"
                      >
                        创建场景
                      </el-button>
                    </div>
                  </div>
                </div>
                
                <div class="form-item">
                  <div class="form-label">场景描述</div>
                  <el-input
                    v-model="item.sceneDesc"
                    type="textarea"
                    :rows="2"
                    placeholder="请输入场景描述"
                    @change="handleItemChange(item, index)"
                  />
                </div>
                
                <div class="form-actions">
                  <el-button 
                    color="#1c1d29" 
                    @click="handleSaveStoryboardItem(item, index)"
                  >
                    确认
                  </el-button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 场景选择对话框 -->
    <el-dialog
      v-model="sceneSelectDialogVisible"
      title="选择场景"
      width="500px"
      destroy-on-close
    >
      <el-form>
        <el-form-item label="场景">
          <div class="scene-select-container">
            <div v-if="scenesList.length === 0" class="scene-empty-state">
              <div class="scene-empty-overlay">
                <el-button color="#1c1d29" size="small" @click="openPreGenerateScene">去确认</el-button>
              </div>
            </div>
            <el-select v-else v-model="selectedSceneId" :suffix-icon="CaretBottom" style="width: 100%">
              <el-option
                v-for="scene in scenesList"
                :key="scene.id"
                :label="scene.name"
                :value="scene.id"
              />
            </el-select>
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="sceneSelectDialogVisible = false">取消</el-button>
          <el-button color="#1c1d29" @click="confirmSelectScene" :disabled="scenesList.length === 0">确认</el-button>
        </div>
      </template>
    </el-dialog>
    
    <!-- 预生成图片弹窗 -->
    <pre-generate-dialog
      v-model:visible="preGenerateVisible"
      :initial-description="currentScenePrompt"
      :scene-id="currentEditingScene?.id"
      @confirm="handlePreGenerateConfirm"
      @cancel="preGenerateVisible = false"
    />
    
    <!-- 分镜项目弹窗 -->
    <el-dialog
      v-model="storyboardItemDialogVisible"
      :title="isEditStoryboardItem ? '编辑分镜' : '新增分镜'"
      width="90%"
      destroy-on-close
      class="storyboard-item-dialog"
    >
      <el-form
        ref="storyboardItemFormRef"
        :model="storyboardItemForm"
        :rules="storyboardItemRules"
        label-width="100px"
        label-position="top"
        class="storyboard-form"
      >
        <div class="form-content">
          <el-form-item label="分镜名称" prop="sbNo">
            <el-input v-model="storyboardItemForm.sbNo" placeholder="请输入分镜名称" />
          </el-form-item>
          
          <el-form-item label="镜头描述" prop="sbDesc">
            <el-input
              v-model="storyboardItemForm.sbDesc"
              type="textarea"
              :rows="3"
              placeholder="请输入镜头描述"
            />
          </el-form-item>
          
          <el-form-item label="场景" prop="sceneUrl">
            <el-input
              v-model="storyboardItemForm.sceneUrl"
              type="textarea"
              :rows="2"
              placeholder="请输入场景描述"
            />
          </el-form-item>
          
          <el-form-item label="图片提示词" prop="imagePrompt">
            <el-input
              v-model="storyboardItemForm.imagePrompt"
              type="textarea"
              :rows="2"
              placeholder="请输入图片提示词"
            />
          </el-form-item>
          
          <el-form-item label="视频提示词" prop="videoPrompt">
            <el-input
              v-model="storyboardItemForm.videoPrompt"
              type="textarea"
              :rows="2"
              placeholder="请输入视频提示词"
            />
          </el-form-item>
          
          <el-form-item label="角色" prop="actors">
            <div class="actors-container">
              <div class="actors-wrapper">
                <div v-for="(actor, index) in storyboardItemForm.actors" :key="index" class="actor-item">
                  <div class="actor-header">
                    <h4 class="actor-title">角色 {{ index + 1 }}</h4>
                    <el-button 
                       
                      size="small" 
                      @click="handleRemoveActor(index)"
                      class="delete-actor-btn"
                    >
                      <el-icon><Delete /></el-icon>
                    </el-button>
                  </div>
                  
                  <div class="actor-form-grid">
                    <div class="actor-form-item">
                      <el-form-item label="角色名称" :prop="`actors[${index}].actorId`" :rules="{ required: true, message: '请选择角色', trigger: 'change' }">
                        <el-select v-model="actor.actorId" placeholder="请选择角色" style="width: 100%" @change="handleActorChange(index)">
                          <el-option
                            v-for="role in roles"
                            :key="role.id"
                            :label="role.actorName"
                            :value="role.actorId"
                          />
                        </el-select>
                      </el-form-item>
                    </div>
                    
                    <div class="actor-form-item">
                      <el-form-item label="人物视角" :prop="`actors[${index}].perspective`" :rules="{ required: true, message: '请选择人物视角', trigger: 'change' }">
                        <el-select v-model="actor.perspective" placeholder="请选择人物视角" style="width: 100%" @change="handlePerspectiveChange(index)">
                          <el-option label="主图" value="WHOLE_BODY_FRONT" />
                          <el-option label="侧图" value="WHOLE_BODY_SIDE" />
                          <el-option label="背图" value="WHOLE_BODY_BACK" />
                          <el-option label="半身图" value="HALF_BODY" />
                        </el-select>
                      </el-form-item>
                    </div>
                  </div>
                  
                  <div class="actor-preview" v-if="actor.previewUrl">
                    <div class="preview-title">图片预览</div>
                    <div class="preview-image-container">
                      <img :src="actor.previewUrl" class="preview-image" alt="角色预览" />
                    </div>
                  </div>
                  <div class="actor-preview empty-preview" v-else-if="actor.actorName">
                    <div class="preview-title">图片预览</div>
                    <div class="preview-empty">未找到对应视角的图片</div>
                  </div>
                </div>
              </div>
              
              <el-button color="#1c1d29" @click="handleAddActor" class="add-actor-btn">
                <el-icon class="mr-1"><Plus /></el-icon>添加角色
              </el-button>
            </div>
          </el-form-item>
        </div>
      </el-form>
      
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="storyboardItemDialogVisible = false">取消</el-button>
          <el-button 
            color="#1c1d29" 
            @click="handleSaveStoryboardItem" 
            :loading="saveStoryboardItemLoading"
          >
            保存
          </el-button>
        </div>
      </template>
    </el-dialog>
    
    <!-- 图集弹窗 -->
    <el-dialog
      v-model="galleryDialogVisible"
      title="图集详情"
      width="80%"
      destroy-on-close
      class="custom-dialog"
      @close="handleGalleryDialogClose"
    >
      <template v-if="currentEpisode">
        <div class="mb-6">
          <div class="font-bold mb-2">{{ currentEpisode.name }}</div>
          <div class="flex items-center space-x-4">
            <el-button 
              color="#1c1d29" 
              @click="handlePrevStoryboard"
              :disabled="currentStoryboardIndex <= 0"
            >
              <el-icon class="mr-1"><ArrowLeft /></el-icon>上一个
            </el-button>
            
            <el-select 
              :suffix-icon="CaretBottom"
              v-model="currentStoryboardIndex" 
              placeholder="选择分镜"
              style="width: 300px"
            >
              <el-option
                v-for="(item, index) in storyboardItems"
                :key="index"
                :label="`分镜${item.sbNo}`"
                :value="index"
              />
            </el-select>
            
            <el-button 
              color="#1c1d29" 
              @click="handleNextStoryboard"
              :disabled="currentStoryboardIndex >= storyboardItems.length - 1"
            >
              下一个<el-icon class="ml-1"><ArrowRight /></el-icon>
            </el-button>
          </div>
          
          <!-- 分镜描述 -->
          <div v-if="currentStoryboard && currentStoryboard.sbDesc" class="storyboard-description mt-4 p-4 bg-gray-50 rounded-lg">
            <div class="text-sm text-gray-600 font-bold mb-2">分镜描述：</div>
            <div class="text-sm whitespace-pre-wrap">{{ currentStoryboard.sbDesc }}</div>
          </div>
          
          <!-- 视频提示词 -->
          <div v-if="currentStoryboard && currentStoryboard.videoPrompt" class="storyboard-description video-prompt mt-4 p-4 bg-gray-50 rounded-lg">
            <div class="text-sm text-gray-600 font-bold mb-2">视频提示词：</div>
            <div class="text-sm whitespace-pre-wrap">{{ currentStoryboard.videoPrompt }}</div>
          </div>
        </div>
        
        <el-divider />
        
        <div class="grid grid-cols-2 gap-6">
          <!-- 图集列表 -->
          <div class="gallery-list">
            <div class="font-bold mb-4">图集列表</div>
            <div v-if="galleryImages.length > 0" class="grid grid-cols-3 gap-2">
              <div 
                v-for="(image, index) in galleryImages"
                :key="index"
                class="gallery-item cursor-pointer"
                :class="{ 'gallery-item-active': selectedImageIndex === index }"
                @click="handleSelectImage(index)"
              >
                <img :src="image.url" class="gallery-thumbnail" />
              </div>
            </div>
            <div v-else class="empty-gallery-container">
              <el-empty description="暂无分镜图，请初始化" :image-size="120">
                <el-button 
                  color="#1c1d29" 
                  @click="handleGenerateImages"
                  :loading="generatingImages"
                >
                  <el-icon class="mr-1"><Plus /></el-icon>立即生成
                </el-button>
              </el-empty>
            </div>
          </div>
          
          <!-- 预览及操作 -->
          <div class="gallery-preview">
            <div class="font-bold mb-4">预览及操作</div>
            
            <!-- 选中图片 -->
            <div class="mb-4">
              <div class="text-gray-500 mb-2">选中图片</div>
              <div class="selected-image-container bg-gray-100 rounded-lg">
                <img 
                  v-if="selectedImage" 
                  :src="selectedImage.url" 
                  class="selected-image" 
                />
                <div v-else class="selected-image-placeholder">
                  请选择图片
                </div>
              </div>
              
              <div class="mt-4 flex justify-between">
                <el-button 
                  color="#1c1d29" 
                  @click="handleDownloadImage"
                  :disabled="!selectedImage"
                >
                  <el-icon class="mr-1"><Download /></el-icon>下载
                </el-button>
                
                <el-button
                  type="warning"
                  @click="handleSetAsStoryboardImage"
                  :disabled="!selectedImage"
                >
                  <el-icon class="mr-1"><Star /></el-icon>设定为用图
                </el-button>
                
                <el-upload
                  :show-file-list="false"
                  :before-upload="beforeGalleryImageUpload"
                  :http-request="handleGalleryImageUpload"
                >
                  <el-button 
                    
                  >
                    <el-icon class="mr-1"><Upload /></el-icon>上传新图片
                  </el-button>
                </el-upload>
              </div>
            </div>
            
            <!-- 提示词 -->
            <div class="mb-4">
              <div class="text-gray-500 mb-2">提示词 <el-tag size="small" type="info" class="ml-2">图片提示词</el-tag></div>
              <el-input
                v-model="selectedImagePrompt"
                type="textarea"
                :rows="3"
                placeholder="请输入提示词"
                
              />
            </div>
            
            <!-- 已选中画面 -->
            <div>
              <div class="text-gray-500 mb-2">已选中画面</div>
              <div class="selected-images-container bg-gray-50 p-4 rounded-lg">
                <div v-if="selectedStoryboardImages.length > 0" class="grid grid-cols-4 gap-2">
                  <div 
                    v-for="(image, index) in selectedStoryboardImages"
                    :key="index"
                    class="selected-storyboard-image cursor-pointer"
                    :class="{ 'current-storyboard-image': image.storyboardIndex === currentStoryboardIndex }"
                    @click="openImagePreview(index)"
                  >
                    <img :src="image.url" class="w-full h-16 object-cover rounded" />
                    <div class="text-xs text-center mt-1 truncate">{{ image.storyboardName }}</div>
                  </div>
                </div>
                <div v-else class="text-gray-400 text-center py-4">
                  暂无已选中画面
                </div>
              </div>
            </div>
          </div>
        </div>
      </template>
    </el-dialog>
    
    <!-- 新增剧集弹窗 -->
    <el-dialog
      v-model="addEpisodeDialogVisible"
      title="新增剧集"
      width="500px"
      destroy-on-close
      class="add-episode-dialog"
    >
      <el-form
        ref="addEpisodeFormRef"
        :model="addEpisodeForm"
        :rules="addEpisodeRules"
        label-width="80px"
        label-position="top"
      >
        <el-form-item label="剧集编号" prop="segNo">
          <el-input 
            v-model.number="addEpisodeForm.segNo" 
            placeholder="请输入剧集编号" 
            type="number"
          />
        </el-form-item>
        
        <el-form-item label="剧集内容" prop="content">
          <el-input
            v-model="addEpisodeForm.content"
            type="textarea"
            :rows="4"
            placeholder="请输入剧集内容"
          />
        </el-form-item>
      </el-form>
      
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="addEpisodeDialogVisible = false">取消</el-button>
          <el-button 
            color="#1c1d29" 
            @click="handleConfirmAddEpisode" 
            :loading="addEpisodeLoading"
          >
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>
    
    
    <!-- 图片预览弹窗 -->
    <el-dialog
      v-model="imagePreviewVisible"
      :title="`图片预览 - ${currentPreviewImage ? currentPreviewImage.storyboardName : ''}`"
      width="80%"
      class="image-preview-dialog"
      destroy-on-close
      top="5vh"
      @close="resetPreviewZoom"
    >
      <div class="image-preview-container">
        <div class="image-preview-wrapper">
          <!-- 图片预览 -->
          <div
            v-if="currentPreviewImage" 
            class="image-zoom-container"
            :style="{ transform: `scale(${previewZoom})` }"
          >
            <img 
              :src="currentPreviewImage.url" 
              class="preview-image" 
              alt="预览图片"
            />
          </div>
          
          <!-- 导航按钮 -->
          <div class="image-nav-buttons">
            <el-tooltip content="上一张 (←)" placement="top">
              <el-button 
                color="#1c1d29" 
                circle 
                class="prev-button" 
                @click="prevImage" 
                :disabled="previewImageIndex <= 0"
              >
                <el-icon><ArrowLeft /></el-icon>
              </el-button>
            </el-tooltip>
            
            <el-tooltip content="下一张 (→)" placement="top">
              <el-button 
                color="#1c1d29" 
                circle 
                class="next-button" 
                @click="nextImage" 
                :disabled="previewImageIndex >= selectedStoryboardImages.length - 1"
              >
                <el-icon><ArrowRight /></el-icon>
              </el-button>
            </el-tooltip>
          </div>
          
          <!-- 缩放控制 -->
          <div class="zoom-controls">
            <el-tooltip content="缩小 (-)" placement="top">
              <el-button 
                circle
                size="small"
                @click="zoomOut"
                :disabled="previewZoom <= 0.5"
                class="zoom-button"
              >
                <el-icon><ZoomOut /></el-icon>
              </el-button>
            </el-tooltip>
            
            <el-tooltip content="重置缩放" placement="top">
              <el-button 
                size="small"
                @click="resetPreviewZoom"
                class="zoom-reset-button"
              >
                {{ Math.round(previewZoom * 100) }}%
              </el-button>
            </el-tooltip>
            
            <el-tooltip content="放大 (+)" placement="top">
              <el-button 
                circle
                size="small"
                @click="zoomIn"
                :disabled="previewZoom >= 3"
                class="zoom-button"
              >
                <el-icon><ZoomIn /></el-icon>
              </el-button>
            </el-tooltip>
          </div>
        </div>
        
        <!-- 缩略图导航 -->
        <div class="image-thumbnails">
          <div 
            v-for="(image, index) in selectedStoryboardImages" 
            :key="index"
            class="image-thumbnail"
            :class="{ 'active': index === previewImageIndex }"
            @click="previewImageIndex = index"
          >
            <img :src="image.url" :alt="`缩略图 ${index + 1}`" />
            <div class="text-xs mt-1 truncate">{{ image.storyboardName }}</div>
          </div>
        </div>
        
        <!-- 图片信息 -->
        <div v-if="currentPreviewImage" class="image-info mt-4">
          <div class="flex justify-between items-center mb-2">
            <div>
              <div class="text-sm text-gray-600">对应分镜：{{ currentPreviewImage.storyboardName }}</div>
              <div class="text-sm text-gray-600">图片序号：{{ previewImageIndex + 1 }} / {{ selectedStoryboardImages.length }}</div>
            </div>
            <div class="flex space-x-2">
              <el-button 
                color="#1c1d29" 
                size="small" 
                @click="handleDownloadPreviewImage"
              >
                <el-icon class="mr-1"><Download /></el-icon>下载图片
              </el-button>
              
              <el-button 
                type="warning" 
                size="small" 
                @click="setAsCurrentStoryboardImage(currentPreviewImage.storyboardIndex)"
                v-if="canSetAsCurrentStoryboardImage(currentPreviewImage.storyboardIndex)"
              >
                设定为用图
              </el-button>
            </div>
          </div>
          
          <div class="keyboard-shortcuts">
            <div class="text-sm font-bold mb-1">键盘快捷键:</div>
            <div class="shortcuts-grid">
              <div><kbd>←</kbd> <span>上一张</span></div>
              <div><kbd>→</kbd> <span>下一张</span></div>
              <div><kbd>+</kbd> <span>放大</span></div>
              <div><kbd>-</kbd> <span>缩小</span></div>
              <div><kbd>0</kbd> <span>重置缩放</span></div>
              <div><kbd>D</kbd> <span>下载图片</span></div>
              <div><kbd>ESC</kbd> <span>关闭预览</span></div>
            </div>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { deleteStoryboard, generateStoryboardImage, getDramaSeries, getDramaStoryboard, preInitStoryboard, queryStoryboardImageList, saveOrUpdateStoryboard, addSeries, updateSeries, reSplitSeries } from '@/api/drama'
import PreGenerateDialog from '@/components/common/PreGenerateDialog.vue'
import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
import { computed, nextTick, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import StoryboardDetail from './StoryboardDetail.vue'

import { ArrowLeft, ArrowRight, Delete, Download, Loading, Plus, Star, Upload, ZoomIn, ZoomOut, CaretBottom } from '@element-plus/icons-vue'

const router = useRouter()

const props = defineProps({
  completeLoading: {
    type: Boolean,
    default: true
  },
  episodes: {
    type: Array,
    default: () => []
  },
  roles: {
    type: Array,
    default: () => []
  },
  scenes: {
    type: Array,
    default: () => []
  },
  disabled: {
    type: Boolean,
    default: false
  },
  dramaId: {
    type: String,
    default: ''
  }
})

const emit = defineEmits(['update:episodes', 'switch-tab', 'select-series'])

// 分集列表
const loading = ref(false)
const initSeriesLoading = ref(false)

// 分镜弹窗
const storyboardDialogVisible = ref(false)
const storyboardActiveTab = ref('script')
const currentEpisode = ref(null)
const storyboardItems = ref([])
const storyboardLoading = ref(false)
const initLoading = ref(false)
const savingStoryboard = ref(false)
const pollingTimer = ref(null)
const pollingCount = ref(0)
const maxPollingCount = ref(120) // 10分钟，每5秒一次，共120次

// 是否是第一次分镜初始化状态位
const isFirstInitStoryboard = ref(true)

// 开始轮询分镜初始化状态
const startPollingStoryboardInit = () => {
  if (!currentEpisode.value || !currentEpisode.value.seriesId) {
    ElMessage.error('无效的分集数据')
    return
  }
  
  // 清除可能存在的轮询定时器
  if (pollingTimer.value) {
    clearInterval(pollingTimer.value)
  }
  
  // 重置计数器
  pollingCount.value = 0
  storyboardLoading.value = true
  initLoading.value = true
  
  const dramaId = currentEpisode.value.dramaId
  const seriesId = currentEpisode.value.seriesId
  
  // 设置轮询间隔为5秒
  pollingTimer.value = setInterval(async () => {
    try {
      pollingCount.value++
      
      // 如果超过最大轮询次数，停止轮询
      if (pollingCount.value > maxPollingCount.value) {
        clearInterval(pollingTimer.value)
        pollingTimer.value = null
        storyboardLoading.value = false
        initLoading.value = false
        ElMessage.warning('本次初始化已超时，请重试')
        return
      }

      
      clearInterval(pollingTimer.value)
      pollingTimer.value = null
      storyboardLoading.value = false
      initLoading.value = false
      
      // 调用预初始化API
      const { data } = await preInitStoryboard(dramaId, seriesId)
      
      // 检查状态
      if (data && data.status === 4) {
        // 初始化成功
        clearInterval(pollingTimer.value)
        pollingTimer.value = null
        
        // 获取初始化后的分镜列表
        const { data: storyboardData } = await getDramaStoryboard(seriesId,{
          pageSize: 1,
          pageNum: 1000
        })
        storyboardItems.value = storyboardData || []
        
        // 更新分集数据
        updateEpisodeStoryboardItems()
        
        // 设置为第一次初始化状态，以便显示保存按钮
        isFirstInitStoryboard.value = true
        
        storyboardLoading.value = false
        initLoading.value = false
        ElMessage.success('分镜初始化成功')
      } else if (data && data.status === -1) {
        // 初始化失败
        clearInterval(pollingTimer.value)
        pollingTimer.value = null
        storyboardLoading.value = false
        initLoading.value = false
        ElMessage.error('初始化失败，请重试')
      }
      // 其他状态继续轮询
    } catch (error) {
      console.error('轮询分镜初始化状态失败:', error)
      // 发生错误时不停止轮询，继续尝试
    }
  }, 5000) // 每5秒轮询一次
}

// 停止轮询
const stopPollingStoryboardInit = () => {
  if (pollingTimer.value) {
    clearInterval(pollingTimer.value)
    pollingTimer.value = null
  }
  storyboardLoading.value = false
  initLoading.value = false
}

// 监听弹窗关闭
watch(storyboardDialogVisible, (newVal) => {
  if (!newVal) {
    // 弹窗关闭时停止轮询
    stopPollingStoryboardInit()
  }
})

// 分镜项目弹窗
const storyboardItemDialogVisible = ref(false)
const isEditStoryboardItem = ref(false)
const editStoryboardItemIndex = ref(-1)
const saveStoryboardItemLoading = ref(false)
const storyboardItemFormRef = ref(null)

const storyboardItemForm = reactive({
  sbNo: '',
  actors: [],
  sbDesc: '',
  sceneUrl: '',
  imagePrompt: '',
  videoPrompt: ''
})

const storyboardItemRules = {
  sbNo: [
    { required: true, message: '请输入分镜名称', trigger: 'blur' }
  ],
  actors: [
    { required: true, message: '请添加角色', trigger: 'change' }
  ],
  sbDesc: [
    { required: true, message: '请输入镜头描述', trigger: 'blur' }
  ],
  sceneUrl: [
    { required: true, message: '请输入场景描述', trigger: 'blur' }
  ]
}

// 添加角色
const handleAddActor = () => {
  storyboardItemForm.actors.push({ 
    actorId: '', 
    actorName: '', 
    perspective: 'WHOLE_BODY_FRONT',
    previewUrl: '' // 添加预览图片URL字段
  })
}

// 移除角色
const handleRemoveActor = (index) => {
  storyboardItemForm.actors.splice(index, 1)
}

// 处理角色变化
const handleActorChange = (index) => {
  const actor = storyboardItemForm.actors[index]
  // 重置预览图片
  actor.previewUrl = ''
  
  // 根据选择的actorId查找对应的角色信息
  const selectedRole = props.roles.find(role => role.actorId === actor.actorId)
  
  if (selectedRole) {
    // 设置actorName
    actor.actorName = selectedRole.actorName
    
    // 如果选择了角色和视角，尝试获取预览图片
    if (actor.actorName && actor.perspective) {
      updateActorPreview(index)
    }
  }
}

// 处理视角变化
const handlePerspectiveChange = (index) => {
  const actor = storyboardItemForm.actors[index]
  // 重置预览图片
  actor.previewUrl = ''
  
  // 如果选择了角色和视角，尝试获取预览图片
  if (actor.actorId && actor.perspective) {
    updateActorPreview(index)
  }
}

// 更新角色预览图片
const updateActorPreview = (index) => {
  const actor = storyboardItemForm.actors[index]
  const selectedRole = props.roles.find(role => role.actorId === actor.actorId)
  
  if (!selectedRole) return
  
  // 根据视角获取对应的图片URL
  switch (actor.perspective) {
    case 'WHOLE_BODY_FRONT':
      actor.previewUrl = selectedRole.wholeBodyFrontImageUrl || ''
      break
    case 'WHOLE_BODY_SIDE':
      actor.previewUrl = selectedRole.wholeBodySideImageUrl || ''
      break
    case 'WHOLE_BODY_BACK':
      actor.previewUrl = selectedRole.wholeBodyBackImageUrl || ''
      break
    case 'HALF_BODY':
      actor.previewUrl = selectedRole.halfBodyImageUrl || ''
      break
    default:
      actor.previewUrl = ''
  }
}

// 添加分镜项目
const handleAddStoryboardItem = () => {
  isEditStoryboardItem.value = false
  editStoryboardItemIndex.value = -1
  
  // 清空表单
  storyboardItemForm.sbNo = ''
  storyboardItemForm.actors = []
  storyboardItemForm.sbDesc = ''
  storyboardItemForm.sceneUrl = '' // 清空场景描述
  storyboardItemForm.imagePrompt = '' // 清空图片提示词
  storyboardItemForm.videoPrompt = '' // 清空视频提示词
  
  // 默认添加一个空角色
  handleAddActor()
  
  storyboardItemDialogVisible.value = true
  
  // 重置表单校验
  nextTick(() => {
    storyboardItemFormRef.value && storyboardItemFormRef.value.resetFields()
  })
}

// 编辑分镜项目
const handleEditStoryboardItem = (item, index) => {
  isEditStoryboardItem.value = true
  editStoryboardItemIndex.value = index
  
  // 清空表单
  storyboardItemForm.sbNo = ''
  storyboardItemForm.actors = []
  storyboardItemForm.sbDesc = ''
  storyboardItemForm.sceneUrl = ''
  storyboardItemForm.imagePrompt = ''
  storyboardItemForm.videoPrompt = ''
  
  // 填充表单
  storyboardItemForm.sbNo = item.sbNo || ''
  storyboardItemForm.sbDesc = item.sbDesc || ''
  storyboardItemForm.sceneUrl = item.sceneUrl || ''
  storyboardItemForm.imagePrompt = item.imagePrompt || ''
  storyboardItemForm.videoPrompt = item.videoPrompt || ''
  
  // 填充角色数组
  if (item.actors && Array.isArray(item.actors) && item.actors.length > 0) {
    storyboardItemForm.actors = item.actors.map(actor => ({
      actorId: actor.actorId || '',
      actorName: actor.actorName || '',
      perspective: actor.perspective || 'WHOLE_BODY_FRONT',
      previewUrl: '' // 初始化预览URL
    }))
    
    // 为每个角色获取预览图片
    nextTick(() => {
      storyboardItemForm.actors.forEach((actor, idx) => {
        if (actor.actorId && actor.perspective) {
          updateActorPreview(idx)
        }
      })
    })
  } else {
    // 如果没有角色，添加一个空角色
    handleAddActor()
  }
  
  storyboardItemDialogVisible.value = true
  
  // 重置表单校验
  nextTick(() => {
    storyboardItemFormRef.value && storyboardItemFormRef.value.resetFields()
  })
}

// 删除分镜项目
const handleDeleteStoryboardItem = (index) => {
  ElMessageBox.confirm('确定要删除该分镜吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
    confirmButtonClass: 'confirm-delete-btn-class'
  }).then(async () => {
    try {
      const item = storyboardItems.value[index]
      
      // 检查是否有必要的ID
      if (!currentEpisode.value || !currentEpisode.value.seriesId) {
        throw new Error('分集信息缺失')
      }
      
      // 第一次初始化时不调用接口，或者没有sbId，直接从本地删除
      if (isFirstInitStoryboard.value || !item || !item.sbId) {
        const updatedItems = [...storyboardItems.value]
        updatedItems.splice(index, 1)
        storyboardItems.value = updatedItems
        
        // 更新分集数据
        updateEpisodeStoryboardItems()
        
        ElMessage.success('分镜删除成功')
        return
      }
      
      const dramaId = currentEpisode.value.dramaId
      const seriesId = currentEpisode.value.seriesId
      
      // 调用删除接口
      await deleteStoryboard(dramaId, seriesId, item.sbId)
      
      // 更新本地数据
      const updatedItems = [...storyboardItems.value]
      updatedItems.splice(index, 1)
      storyboardItems.value = updatedItems
      
      // 更新分集数据
      updateEpisodeStoryboardItems()
      
      ElMessage.success('分镜删除成功')
    } catch (error) {
      console.error('删除分镜失败:', error)
      ElMessage.error('删除失败，请重试')
    }
  }).catch(() => {})
}

// 保存分镜项目
const handleSaveStoryboardItem = async () => {
  // 表单验证
  try {
    await storyboardItemFormRef.value.validate()
  } catch (error) {
    return
  }
  
  // 检查是否至少有一个角色
  if (!storyboardItemForm.actors || storyboardItemForm.actors.length === 0) {
    ElMessage.warning('请至少添加一个角色')
    return
  }
  
  saveStoryboardItemLoading.value = true
  
  try {
    if (!currentEpisode.value || !currentEpisode.value.seriesId) {
      throw new Error('分集信息缺失')
    }
    
    const dramaId = currentEpisode.value.dramaId
    const seriesId = currentEpisode.value.seriesId
    
    const itemData = {
      sbNo: storyboardItemForm.sbNo,
      actors: storyboardItemForm.actors.map(actor => ({
        actorId: actor.actorId,
        actorName: actor.actorName,
        perspective: actor.perspective
        // 不保存预览URL，因为它是前端计算出来的
      })),
      sbDesc: storyboardItemForm.sbDesc,
      sceneUrl: storyboardItemForm.sceneUrl,
      imagePrompt: storyboardItemForm.imagePrompt,
      videoPrompt: storyboardItemForm.videoPrompt
    }
    
    // 如果是编辑模式，添加sbId
    if (isEditStoryboardItem.value && editStoryboardItemIndex.value !== -1) {
      const originalItem = storyboardItems.value[editStoryboardItemIndex.value]
      if (originalItem && originalItem.sbId) {
        itemData.sbId = originalItem.sbId
      }
    }
    
    // 第一次初始化时不调用接口，只在本地保存
    if (isFirstInitStoryboard.value) {
      if (isEditStoryboardItem.value && editStoryboardItemIndex.value !== -1) {
        // 编辑模式
        const updatedItems = [...storyboardItems.value]
        updatedItems[editStoryboardItemIndex.value] = itemData
        storyboardItems.value = updatedItems
      } else {
        // 新增模式
        storyboardItems.value.push(itemData)
      }
      
      // 更新分集数据
      updateEpisodeStoryboardItems()
      
      ElMessage.success(isEditStoryboardItem.value ? '分镜更新成功' : '分镜添加成功')
      storyboardItemDialogVisible.value = false
      return
    }
    
    // 非第一次初始化时调用保存或更新接口
    const { data } = await saveOrUpdateStoryboard(dramaId, seriesId, itemData)
    
    if (data) {
      if (isEditStoryboardItem.value && editStoryboardItemIndex.value !== -1) {
        // 编辑模式
        const updatedItems = [...storyboardItems.value]
        updatedItems[editStoryboardItemIndex.value] = data
        storyboardItems.value = updatedItems
      } else {
        // 新增模式
        storyboardItems.value.push(data)
      }
      
      // 更新分集数据
      updateEpisodeStoryboardItems()
      
      ElMessage.success(isEditStoryboardItem.value ? '分镜更新成功' : '分镜添加成功')
      storyboardItemDialogVisible.value = false
    } else {
      ElMessage.warning('保存失败，返回数据为空')
    }
  } catch (error) {
    console.error('保存分镜失败:', error)
    ElMessage.error('保存失败，请重试')
  } finally {
    saveStoryboardItemLoading.value = false
  }
}

// 更新分集的分镜项目
const updateEpisodeStoryboardItems = () => {
  if (!currentEpisode.value) return
  
  const updatedEpisode = { ...currentEpisode.value }
  updatedEpisode.storyboard.items = storyboardItems.value
  
  const updatedEpisodes = props.episodes.map(item => {
    if (item.id === updatedEpisode.id) {
      return updatedEpisode
    }
    return item
  })
  
  emit('update:episodes', updatedEpisodes)
}

// 图集弹窗
const galleryDialogVisible = ref(false)
const galleryImages = ref([])
const selectedImageIndex = ref(-1)
const selectedImagePrompt = ref('')
const currentStoryboardIndex = ref(0)
const generatingImages = ref(false)
const refreshingImages = ref(false)
// 存储所有分镜的图集列表
const storyboardGalleries = ref(new Map())

// 计算选中的图片
const selectedImage = computed(() => {
  if (selectedImageIndex.value === -1 || !galleryImages.value.length) return null
  return galleryImages.value[selectedImageIndex.value]
})

// 计算已选中的分镜图片
const selectedStoryboardImages = computed(() => {
  if (!currentEpisode.value || !storyboardItems.value.length) return []
  
  const result = []
  // 只显示当前分镜及之前的已设定用图的分镜
  for (let i = 0; i <= currentStoryboardIndex.value; i++) {
    const storyboard = storyboardItems.value[i]
    if (storyboard && storyboard.selectedImage) {
      result.push({
        url: storyboard.selectedImage,
        storyboardName: storyboard.sbNo,
        storyboardIndex: i
      })
    }
  }
  
  return result
})

// 计算当前选中的分镜
const currentStoryboard = computed(() => {
  if (!storyboardItems.value.length || currentStoryboardIndex.value < 0 || currentStoryboardIndex.value >= storyboardItems.value.length) {
    return null;
  }
  return storyboardItems.value[currentStoryboardIndex.value];
})

// 选择图片
const handleSelectImage = (index) => {
  selectedImageIndex.value = index
  // 设置提示词，优先使用图片的prompt，如果没有则使用从API获取的videoPrompt
  selectedImagePrompt.value = galleryImages.value[index].prompt || ''
}

// 监听当前分镜索引变化
watch(currentStoryboardIndex, async (newIndex) => {
  if (!currentEpisode.value) return;
  
  try {
    // 获取当前分镜的图片列表
    if (storyboardItems.value.length > 0 && newIndex >= 0 && newIndex < storyboardItems.value.length) {
      const currentStoryboard = storyboardItems.value[newIndex];
      
      if (currentStoryboard && currentStoryboard.sbId) {
        const dramaId = currentEpisode.value.dramaId || currentEpisode.value.seriesId.split('_')[0];
        const sbId = currentStoryboard.sbId;
        const sbNo = currentStoryboard.sbNo;
        
        // 检查map中是否已有该分镜的图集数据
        if (storyboardGalleries.value.has(sbNo)) {
          // 直接使用map中存储的图集数据
          galleryImages.value = storyboardGalleries.value.get(sbNo);
        } else {
          // 从API获取图集数据
          const { data: imageData } = await queryStoryboardImageList(dramaId, sbId);
          
          if (imageData && imageData.imageProcess && imageData.imageProcess.imageUrlList.length > 0) {
            // 使用返回的图片列表替换当前图集
            galleryImages.value = imageData.imageProcess.imageUrlList.map((url, index) => ({
              id: `image_${index}`,
              url: url,
              prompt: imageData.videoPrompt || ''
            }));
            
            // 将图集数据存入map
            storyboardGalleries.value.set(sbNo, galleryImages.value);
          } else {
            galleryImages.value = [];
          }
          
          // 更新分镜描述
          if (imageData && imageData.sbDesc) {
            // 更新当前分镜的sbDesc
            const updatedItems = [...storyboardItems.value];
            updatedItems[newIndex] = {
              ...updatedItems[newIndex],
              sbDesc: imageData.sbDesc,
              videoPrompt: imageData.videoPrompt || ''
            };
            storyboardItems.value = updatedItems;
          }
        }
      } else {
        galleryImages.value = [];
      }
    } else {
      galleryImages.value = [];
    }
    
    // 重置选中状态
    selectedImageIndex.value = -1;
    selectedImagePrompt.value = '';
    
    // 如果当前分镜已经有设定的用图，尝试在图集中选中对应的图片
    const currentStoryboard = storyboardItems.value[newIndex];
    if (currentStoryboard && currentStoryboard.selectedImage) {
      // 查找图集中是否有匹配的图片
      const matchingImageIndex = galleryImages.value.findIndex(
        image => image.url === currentStoryboard.selectedImage
      );
      // 如果找到匹配的图片，自动选中它
      if (matchingImageIndex !== -1) {
        selectedImageIndex.value = matchingImageIndex;
        selectedImagePrompt.value = galleryImages.value[matchingImageIndex].prompt || '';
      }
    }
  } catch (error) {
    console.error('获取分镜图片数据失败:', error);
    ElMessage.error('获取分镜图片失败，请重试');
  }
})

// 上一个分镜
const handlePrevStoryboard = () => {
  if (currentStoryboardIndex.value > 0) {
    currentStoryboardIndex.value--
  }
}

// 下一个分镜
const handleNextStoryboard = () => {
  if (currentStoryboardIndex.value < storyboardItems.value.length - 1) {
    currentStoryboardIndex.value++
  }
}

// 上传前验证
const beforeGalleryImageUpload = (file) => {
  const isImage = file.type.startsWith('image/')
  const isLt2M = file.size / 1024 / 1024 < 5
  
  if (!isImage) {
    ElMessage.error('只能上传图片文件!')
    return false
  }
  
  if (!isLt2M) {
    ElMessage.error('图片大小不能超过 5MB!')
    return false
  }
  
  return true
}

// 处理图集图片上传
const handleGalleryImageUpload = (options) => {
  const file = options.file
  
  if (!currentEpisode.value || !currentStoryboard.value) return;
  
  // 使用 FileReader 预览图片
  const reader = new FileReader()
  reader.readAsDataURL(file)
  reader.onload = () => {
    // 添加新图片
    const newImage = {
      id: `image_${Date.now()}`,
      url: reader.result,
      prompt: ''
    }
    
    // 更新当前图集
    galleryImages.value.push(newImage);
    
    // 更新map中存储的图集
    const sbNo = currentStoryboard.value.sbNo
    storyboardGalleries.value.set(sbNo, galleryImages.value)
    
    // 选中新上传的图片
    selectedImageIndex.value = galleryImages.value.length - 1
    selectedImagePrompt.value = ''
    
    ElMessage.success('图片上传成功')
  }
}

// 设定为用图
const handleSetAsStoryboardImage = () => {
  if (!selectedImage.value || !currentEpisode.value || currentStoryboardIndex.value < 0 || storyboardItems.value.length === 0) {
    ElMessage.error('请先选择图片和分镜')
    return
  }
  
  const selectedStoryboard = storyboardItems.value[currentStoryboardIndex.value]
  if (!selectedStoryboard) {
    ElMessage.error('请先选择分镜')
    return
  }
  
  const updatedStoryboard = { ...selectedStoryboard }
  updatedStoryboard.selectedImage = selectedImage.value.url
  
  const updatedItems = [...storyboardItems.value]
  updatedItems[currentStoryboardIndex.value] = updatedStoryboard
  storyboardItems.value = updatedItems
  
  // 确保当前的图集列表也包含这个选中的图片
  const sbNo = selectedStoryboard.sbNo
  if (storyboardGalleries.value.has(sbNo)) {
    const currentGallery = storyboardGalleries.value.get(sbNo)
    // 检查选中的图片是否已经在图集中
    const imageExists = currentGallery.some(img => img.url === selectedImage.value.url)
    if (!imageExists) {
      // 如果不存在，则添加到图集中
      const updatedGallery = [...currentGallery, selectedImage.value]
      storyboardGalleries.value.set(sbNo, updatedGallery)
    }
  } else {
    // 如果map中没有该分镜的图集，则创建一个
    storyboardGalleries.value.set(sbNo, [selectedImage.value])
  }
  
  // 更新分集数据
  updateEpisodeStoryboardItems()
  
  ElMessage.success('已设定为用图')
}

// 图片预览弹窗
const imagePreviewVisible = ref(false)
const previewImageIndex = ref(0)
const previewZoom = ref(1)

// 当前预览图片
const currentPreviewImage = computed(() => {
  if (selectedStoryboardImages.value.length > 0 && 
      previewImageIndex.value >= 0 && 
      previewImageIndex.value < selectedStoryboardImages.value.length) {
    return selectedStoryboardImages.value[previewImageIndex.value]
  }
  return null
})

// 打开图片预览弹窗
const openImagePreview = (index) => {
  previewImageIndex.value = index
  imagePreviewVisible.value = true
}

// 上一个图片
const prevImage = () => {
  if (previewImageIndex.value > 0) {
    previewImageIndex.value--
  }
}

// 下一个图片
const nextImage = () => {
  if (previewImageIndex.value < selectedStoryboardImages.value.length - 1) {
    previewImageIndex.value++
  }
}

// 重置缩放
const resetPreviewZoom = () => {
  previewZoom.value = 1
}

// 放大
const zoomIn = () => {
  previewZoom.value += 0.1
}

// 缩小
const zoomOut = () => {
  previewZoom.value -= 0.1
}

// 键盘导航
const handleKeyDown = (e) => {
  if (!imagePreviewVisible.value) return
  
  if (e.key === 'ArrowLeft') {
    prevImage()
  } else if (e.key === 'ArrowRight') {
    nextImage()
  } else if (e.key === 'Escape') {
    imagePreviewVisible.value = false
  } else if (e.key === '+' || e.key === '=') {
    zoomIn()
  } else if (e.key === '-') {
    zoomOut()
  } else if (e.key === '0') {
    resetPreviewZoom()
  } else if (e.key === 'd' || e.key === 'D') {
    handleDownloadPreviewImage()
  }
}

// 添加键盘事件监听
onMounted(() => {
  getSeriesList()
  window.addEventListener('keydown', handleKeyDown)
})

// 移除键盘事件监听
onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
  
  // 清除轮询定时器
  if (pollingTimer.value) {
    clearInterval(pollingTimer.value)
    pollingTimer.value = null
  }
})

// 判断是否可以设置为当前分镜用图
const canSetAsCurrentStoryboardImage = (storyboardIndex) => {
  return currentStoryboardIndex.value === storyboardIndex && 
         currentEpisode.value.gallery.status !== 'confirmed';
}

// 设置为当前分镜用图
const setAsCurrentStoryboardImage = async (storyboardIndex) => {
  if (canSetAsCurrentStoryboardImage(storyboardIndex)) {
    const img = selectedStoryboardImages.value.find(img => img.storyboardIndex === storyboardIndex);
    if (img) {
      await setCurrentStoryboardImage(img);
    }
  }
}

// 保存分镜列表
const handleConfirmSaveStoryboard = async () => {
  if (!currentEpisode.value || !currentEpisode.value.seriesId) {
    ElMessage.error('无效的分集数据')
    return
  }

  try {
    savingStoryboard.value = true
    
    // 模拟API调用延迟
    setTimeout(() => {
      // 保存成功后，将初始化状态改为false
      isFirstInitStoryboard.value = false
      
      // 确保每个分镜项都有actors属性
      storyboardItems.value = storyboardItems.value.map(item => ({
        ...item,
        actors: item.actors || [{
          actorId: '385303596007552',
          actorName: "林凡",
          perspective: "WHOLE_BODY_FRONT"
        }]
      }))
      
      // 更新分集数据
      updateEpisodeStoryboardItems()
      
      ElMessage.success('分镜列表保存成功')
      savingStoryboard.value = false
    }, 800)
    
  } catch (error) {
    console.error('保存分镜列表失败:', error)
    ElMessage.error('保存失败，请重试')
    savingStoryboard.value = false
  }
}

// 设置当前分镜用图
const setCurrentStoryboardImage = async (image) => {
  if (!currentEpisode.value || !currentEpisode.value.seriesId) {
    ElMessage.error('无效的分集数据')
    return
  }

  try {
    const seriesId = currentEpisode.value.seriesId
    const { data } = await getDramaStoryboard(seriesId)
    
    if (data && Array.isArray(data)) {
      const updatedItems = data.map(item => {
        if (item.sbNo === image.storyboardName) {
          return {
            ...item,
            selectedImage: image.url
          }
        }
        return item
      })
      
      storyboardItems.value = updatedItems
      updateEpisodeStoryboardItems()
      ElMessage.success('已设定为用图')
    } else {
      ElMessage.warning('获取分镜列表失败')
    }
  } catch (error) {
    console.error('设置分镜用图失败:', error)
    ElMessage.error('设置失败，请重试')
  }
}

// 格式化角色名称
const formatActorNames = (actors) => {
  if (!actors || !Array.isArray(actors)) return ''
  return actors.map(actor => actor.actorName || '').filter(name => name).join(', ')
}

// 添加CSS样式
const addStyles = () => {
  // 在这里可以添加动态样式
}

// 刷新图片列表
const refreshImageList = async () => {
  if (!currentEpisode.value || !currentStoryboard.value || !currentStoryboard.value.sbId) {
    ElMessage.error('无效的分镜数据')
    return
  }
  
  try {
    refreshingImages.value = true
    
    const dramaId = currentEpisode.value.dramaId || currentEpisode.value.seriesId.split('_')[0]
    const sbId = currentStoryboard.value.sbId
    const sbNo = currentStoryboard.value.sbNo
    
    // 获取最新的图片列表
    const { data: imageData } = await queryStoryboardImageList(dramaId, sbId)
    
    // 测试数据 - 实际使用时请移除
    galleryImages.value = [
      {
        id: 1,
        url: 'https://picsum.photos/400/225?random=1'
      },
      {
        id: 2,
        url: 'https://picsum.photos/400/225?random=2'
      },
      {
        id: 3,
        url: 'https://picsum.photos/400/225?random=3'
      },
      {
        id: 4,
        url: 'https://picsum.photos/400/225?random=4'
      }
    ]
    
    if (imageData && imageData.imageProcess && imageData.imageProcess.imageUrlList.length > 0) {
      // 使用返回的图片列表替换当前图集
      galleryImages.value = imageData.imageProcess.imageUrlList.map((url, index) => ({
        id: `image_${index}`,
        url: url,
        prompt: imageData.videoPrompt || ''
      }))
      
      // 更新存储在map中的图集数据
      storyboardGalleries.value.set(sbNo, galleryImages.value)
      
      // 重置选中状态
      selectedImageIndex.value = -1
      selectedImagePrompt.value = ''
      
      ElMessage.success('图片列表刷新成功')
    } else {
      ElMessage.info('暂无分镜图')
    }
  } catch (error) {
    console.error('刷新图片列表失败:', error)
    ElMessage.error('刷新失败，请重试')
  } finally {
    refreshingImages.value = false
  }
}

// 处理生成分镜图片
const handleGenerateImages = async () => {
  if (!currentEpisode.value || !currentStoryboard.value || !currentStoryboard.value.sbId) {
    ElMessage.error('无效的分镜数据')
    return
  }
  
  try {
    generatingImages.value = true
    
    const dramaId = currentEpisode.value.dramaId || currentEpisode.value.seriesId.split('_')[0]
    const sbId = currentStoryboard.value.sbId
    const sbNo = currentStoryboard.value.sbNo
    
    // 调用生成接口
    await generateStoryboardImage(dramaId, sbId)
    
    ElMessage.success('图片生成请求已提交，请稍候...')
    
    // 等待2秒后刷新图片列表
    setTimeout(async () => {
      try {
        const { data: imageData } = await queryStoryboardImageList(dramaId, sbId)
        
        // 测试数据 - 实际使用时请移除
        galleryImages.value = [
          {
            id: 1,
            url: 'https://picsum.photos/400/225?random=1'
          },
          {
            id: 2,
            url: 'https://picsum.photos/400/225?random=2'
          },
          {
            id: 3,
            url: 'https://picsum.photos/400/225?random=3'
          },
          {
            id: 4,
            url: 'https://picsum.photos/400/225?random=4'
          }
        ]
        
        if (imageData && imageData.imageProcess && imageData.imageProcess.imageUrlList.length > 0) {
          // 使用返回的图片列表替换当前图集
          galleryImages.value = imageData.imageProcess.imageUrlList.map((url, index) => ({
            id: `image_${index}`,
            url: url,
            prompt: imageData.videoPrompt || ''
          }))
          
          // 更新存储在map中的图集数据
          storyboardGalleries.value.set(sbNo, galleryImages.value)
          
          // 如果生成成功有图片，则自动选中第一张
          if (galleryImages.value.length > 0) {
            selectedImageIndex.value = 0
            selectedImagePrompt.value = galleryImages.value[0].prompt || ''
          }
        } else {
          // 如果没有图片数据，可能还在生成中
          ElMessage.info('图片正在生成中，请稍后刷新查看')
        }
      } catch (error) {
        console.error('获取生成图片失败:', error)
        ElMessage.error('获取生成图片失败，请稍后刷新')
      } finally {
        generatingImages.value = false
      }
    }, 2000)
  } catch (error) {
    console.error('生成分镜图片失败:', error)
    ElMessage.error('生成失败，请重试')
    generatingImages.value = false
  }
}

// 处理图集弹窗关闭
const handleGalleryDialogClose = () => {
  // 保留已经加载的图集数据，不清空map
  // 这样下次打开时可以复用已经加载的数据
  
  // 清空当前显示的图集和选中状态
  galleryImages.value = []
  selectedImageIndex.value = -1
  selectedImagePrompt.value = ''
}


// 处理下载图片
const handleDownloadImage = () => {
  if (!selectedImage.value || !selectedImage.value.url) {
    ElMessage.warning('请先选择一张图片')
    return
  }

  try {
    // 创建一个链接元素
    const link = document.createElement('a')
    
    // 检查URL类型
    if (selectedImage.value.url.startsWith('data:')) {
      // 如果是base64数据，直接使用
      link.href = selectedImage.value.url
    } else {
      // 如果是远程URL，需要先转换为blob
      fetch(selectedImage.value.url)
        .then(response => response.blob())
        .then(blob => {
          const url = window.URL.createObjectURL(blob)
          downloadWithLink(url, getImageFileName())
          // 下载完成后释放URL对象
          setTimeout(() => window.URL.revokeObjectURL(url), 100)
        })
        .catch(error => {
          console.error('下载图片失败:', error)
          ElMessage.error('下载图片失败，请重试')
        })
      return
    }
    
    // 使用链接下载
    downloadWithLink(link.href, getImageFileName())
  } catch (error) {
    console.error('下载图片失败:', error)
    ElMessage.error('下载图片失败，请重试')
  }
}

// 使用链接元素下载文件
const downloadWithLink = (url, fileName) => {
  const link = document.createElement('a')
  link.href = url
  link.download = fileName
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  
  // 显示下载成功消息
  ElMessage.success({
    message: `图片已下载: ${fileName}`,
    duration: 2000
  })
}

// 生成图片文件名
const getImageFileName = () => {
  const now = new Date()
  const timestamp = now.getTime()
  const storyboardName = currentStoryboard.value ? currentStoryboard.value.sbNo : ''
  const imageIndex = selectedImageIndex.value + 1
  
  return `storyboard_${storyboardName}_image_${imageIndex}_${timestamp}.png`
}

// 处理下载预览图片
const handleDownloadPreviewImage = () => {
  if (!currentPreviewImage.value || !currentPreviewImage.value.url) {
    ElMessage.warning('无法下载图片')
    return
  }

  try {
    // 检查URL类型
    if (currentPreviewImage.value.url.startsWith('data:')) {
      // 如果是base64数据，直接使用
      downloadWithLink(currentPreviewImage.value.url, getPreviewImageFileName())
    } else {
      // 如果是远程URL，需要先转换为blob
      fetch(currentPreviewImage.value.url)
        .then(response => response.blob())
        .then(blob => {
          const url = window.URL.createObjectURL(blob)
          downloadWithLink(url, getPreviewImageFileName())
          // 下载完成后释放URL对象
          setTimeout(() => window.URL.revokeObjectURL(url), 100)
        })
        .catch(error => {
          console.error('下载图片失败:', error)
          ElMessage.error('下载图片失败，请重试')
        })
    }
  } catch (error) {
    console.error('下载图片失败:', error)
    ElMessage.error('下载图片失败，请重试')
  }
}

// 生成预览图片文件名
const getPreviewImageFileName = () => {
  const now = new Date()
  const timestamp = now.getTime()
  const storyboardName = currentPreviewImage.value ? currentPreviewImage.value.storyboardName : ''
  const imageIndex = previewImageIndex.value + 1
  
  return `storyboard_${storyboardName}_image_${imageIndex}_${timestamp}.png`
}

// 格式化时间戳
const formatTime = (timestamp) => {
  if (!timestamp) return '-'
  return dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')
}

// 获取状态文本
const getStatusText = (status) => {
  switch (status) {
    case 0:
      return '待确认'
    case 1:
      return '生成中'
    case 2:
      return '已完成'
    default:
      return '待确认'
  }
}

// 获取状态样式类
const getStatusClass = (status) => {
  switch (status) {
    case 0:
      return 'status-pending'
    case 1:
      return 'status-generating'
    case 2:
      return 'status-completed'
    default:
      return 'status-pending'
  }
}

// 判断是否处于生成中状态
const isGenerating = (row) => {
  return row.imageStatus === 1 || row.videoStatus === 1
}

// 判断是否需要生成
const needsGeneration = (row) => {
  return row.imageStatus === 0 || row.videoStatus === 0
}

// 判断是否有角色
const hasRoles = computed(() => {
  console.log(props.roles)
  return props.roles && props.roles.length > 0
})

const scenesList = ref([])

const getSeriesList = async () => {
  const { data } = await getDramaSeries(props.dramaId)
  scenesList.value = data
}


// 跳转到角色页面
const goToRolePage = () => {
  if (!props.dramaId) {
    ElMessage.error('无效的剧本ID')
    return
  }
  router.push(`/drama/edit/${props.dramaId}?tab=role`)
}
// 跳转到场景页面
const goToScenePage = () => {
  if (!props.dramaId) {
    ElMessage.error('无效的剧本ID')
    return
  }
  router.push(`/drama/edit/${props.dramaId}?tab=scene`)
}



// 打开分镜页面 - 替换原来的弹窗打开方式
const handleNavigateToStoryboard = (episode, isEdit) => {
  if (!episode || !episode.seriesId) {
    ElMessage.error('无效的分集数据')
    return
  }
  
  // 使用路由导航到分镜详情页面
  // emit('select-series', episode)
  router.push(`/drama/storyboard/${props.dramaId}/${episode.seriesId}?tab=${(episode.imageStatus ===0 || isEdit) ? '1' : episode.videoStatus === 0 ? '2' : '3'}`)
}

// 场景选择对话框状态
const sceneSelectDialogVisible = ref(false)
const selectedSceneId = ref('')
const currentEditingItem = ref(null)
const currentEditingIndex = ref(-1)

// 预生成弹窗相关
const preGenerateVisible = ref(false)
const currentScenePrompt = ref('')
const currentEditingScene = ref(null)

// 新增剧集弹窗相关
const addEpisodeDialogVisible = ref(false)
const addEpisodeLoading = ref(false)
const addEpisodeFormRef = ref(null)

const addEpisodeForm = reactive({
  segNo: null,
  content: ''
})

const addEpisodeRules = {
  segNo: [
    { required: true, message: '请输入剧集编号', trigger: 'blur' },
    { type: 'number', message: '剧集编号必须为数字', trigger: 'blur' }
  ],
  content: [
    { required: true, message: '请输入剧集内容', trigger: 'blur' }
  ]
}


// 处理选择场景
const handleSelectScene = (item, index) => {
  // 设置当前正在编辑的项目和索引
  currentEditingItem.value = item
  currentEditingIndex.value = index
  selectedSceneId.value = item.sceneId || ''
  
  // 打开场景选择对话框
  sceneSelectDialogVisible.value = true
}

// 确认选择场景
const confirmSelectScene = () => {
  if (selectedSceneId.value && currentEditingItem.value !== null && currentEditingIndex.value !== -1) {
    const selectedScene = props.scenes.find(scene => scene.id === selectedSceneId.value)
    if (selectedScene) {
      const item = currentEditingItem.value
      item.sceneId = selectedScene.id
      item.sceneUrl = selectedScene.name
      item.scenePreviewUrl = selectedScene.previewUrl
      
      // 更新本地数据
      const updatedItems = [...storyboardItems.value]
      updatedItems[currentEditingIndex.value] = item
      storyboardItems.value = updatedItems
      
      ElMessage.success('场景已更新')
    }
  }
  
  // 关闭对话框
  sceneSelectDialogVisible.value = false
}

// 处理创建场景
const handleCreateScene = (item, index) => {
  // 跳转到场景创建页面，并携带回调信息
  router.push({
    path: `/drama/scene/${props.dramaId}`,
    query: { 
      fromStoryboard: true,
      returnPath: router.currentRoute.value.fullPath
    }
  })
}

// 打开预生成场景弹窗
const openPreGenerateScene = () => {
  currentScenePrompt.value = ''
  currentEditingScene.value = {
    id: Date.now().toString(),  // 临时ID
    name: '新场景'
  }
  preGenerateVisible.value = true
}

// 处理预生成确认
const handlePreGenerateConfirm = (imageUrl) => {
  if (currentEditingScene.value && imageUrl) {
    // 创建新场景
    const newScene = {
      id: currentEditingScene.value.id,
      name: currentEditingScene.value.name || '新场景',
      previewUrl: imageUrl,
      sceneImageUrl: imageUrl
    }
    
    // 添加到场景列表
    scenesList.value.push(newScene)
    
    // 选中新创建的场景
    selectedSceneId.value = newScene.id
    
    ElMessage.success('场景创建成功')
  }
  
  // 关闭预生成弹窗
  preGenerateVisible.value = false
}

// 处理新增剧集
const handleAddEpisode = () => {
  // 重置表单
  addEpisodeForm.segNo = null
  addEpisodeForm.content = ''
  
  // 打开弹窗
  addEpisodeDialogVisible.value = true
  
  // 重置表单验证
  nextTick(() => {
    addEpisodeFormRef.value && addEpisodeFormRef.value.resetFields()
  })
}

// 确认新增剧集
const handleConfirmAddEpisode = async () => {
  // 表单验证
  try {
    await addEpisodeFormRef.value.validate()
  } catch (error) {
    return
  }
  
  addEpisodeLoading.value = true
  
  try {
    const requestData = {
      dramaId: parseInt(props.dramaId),
      segNo: addEpisodeForm.segNo,
      content: addEpisodeForm.content
    }
    
    const { data } = await addSeries(requestData)
    
    if (data) {
      ElMessage.success('剧集添加成功')
      addEpisodeDialogVisible.value = false
      
      // 刷新剧集列表
      emit('update:episodes', [...props.episodes, data])
    } else {
      ElMessage.warning('添加失败，返回数据为空')
    }
  } catch (error) {
    console.error('添加剧集失败:', error)
    ElMessage.error('添加失败，请重试')
  } finally {
    addEpisodeLoading.value = false
  }
}

// 重新拆分剧集
const resplit = async (episode) => {
  if (!episode || !episode.seriesId) {
    ElMessage.error('无效的剧集数据')
    return
  }
  
  try {
    // 确认操作
    await ElMessageBox.confirm(
      `确定要重新拆分第${episode.seqNo}集吗？此操作会重新生成分镜数据。`,
      '确认重新拆分',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        confirmButtonClass: 'confirm-delete-btn-class'
      }
    )
    
    ElMessage.info('正在重新拆分，请稍候...')
    
    // 调用重新拆分接口
    const { data } = await reSplitSeries(props.dramaId, episode.seriesId)
    
    if (data) {
      ElMessage.success('重新拆分成功')
      
      // 刷新剧集列表
      await refreshEpisodesList()
    } else {
      ElMessage.warning('重新拆分失败，返回数据为空')
    }
  } catch (error) {
    if (error === 'cancel') {
      // 用户取消操作，不显示错误消息
      return
    }
    console.error('重新拆分剧集失败:', error)
    ElMessage.error('重新拆分失败，请重试')
  }
}

// 刷新剧集列表
const refreshEpisodesList = async () => {
  try {
    loading.value = true
    const { data } = await getDramaSeries(props.dramaId)
    
    if (data) {
      // 通过emit更新父组件的剧集列表
      emit('update:episodes', data)
      ElMessage.success('剧集列表已刷新')
    }
  } catch (error) {
    console.error('刷新剧集列表失败:', error)
    ElMessage.error('刷新剧集列表失败，请重试')
  } finally {
    loading.value = false
  }
}

</script>
<style>
/* 全局移除所有元素的焦点边框 */
* {
  outline: none !important;
}

*:focus, *:focus-visible, *:active {
  border-color: #EBEEF5 !important;
}

.el-button:focus, 
.el-button:focus-visible, 
.el-button:active,
.el-input__inner:focus,
.el-input__wrapper:focus,
.el-textarea__inner:focus,
.el-select:focus,
.el-checkbox:focus,
.el-radio:focus,
.el-switch:focus,
.el-dropdown:focus,
.el-message-box__headerbtn:focus,
.el-upload:focus,
.el-table__row:focus,
.el-table__row td:focus,
.el-table:focus,
.el-table__cell:focus,
.el-table-column:focus,
.el-table__column:focus,
.el-table__inner-wrapper:focus,
.el-table__body:focus,
.el-table__header:focus {
  border-color: #EBEEF5 !important;
}

/* Element Plus 组件样式覆盖 */
  
.el-button--success:focus, 
.el-button--success:active {
  background-color: var(--el-color-success);
  border-color: var(--el-color-success);
}

.el-button--warning:focus, 
.el-button--warning:active {
  background-color: var(--el-color-warning);
  border-color: var(--el-color-warning);
}

.el-button--danger:focus, 
.el-button--danger:active {
  background-color: var(--el-color-danger);
  border-color: var(--el-color-danger);
}
</style>

<style scoped>
.scene-select-container {
  position: relative;
}

.scene-empty-state {
  width: 100%;
  height: 200px;
  background-color: #f5f7fa;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.scene-empty-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
}

.gallery-item {
  border: 2px solid transparent;
  border-radius: 4px;
  overflow: hidden;
  transition: all 0.3s;
}

.gallery-thumbnail {
  width: 100%;
  height: 60px;
  object-fit: cover;
}

.selected-image-container {
  height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.selected-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.selected-image-placeholder {
  color: #909399;
  font-size: 14px;
}

.selected-images-container {
  max-height: 200px;
  overflow-y: auto;
}

.selected-storyboard-image {
  position: relative;
  border: 2px solid transparent;
  border-radius: 4px;
  padding: 2px;
  transition: all 0.3s;
}

.selected-storyboard-image:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.current-storyboard-image {
  border-color: var(--el-color-warning);
  background-color: rgba(255, 230, 180, 0.2);
}

.current-storyboard-image::after {
  content: '当前';
  position: absolute;
  top: 2px;
  right: 2px;
  background-color: var(--el-color-warning);
  color: white;
  font-size: 10px;
  padding: 0 4px;
  border-radius: 2px;
}

.actors-container {
  width: 100%;
}

.actors-container :deep(.el-form-item__content) {
  width: 100%;
}

.actors-wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 25px;
  margin-bottom: 20px;
  width: 100%;
}

@media (max-width: 1600px) {
  .actors-wrapper {
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  }
}

@media (max-width: 1200px) {
  .actors-wrapper {
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  }
}

@media (max-width: 768px) {
  .actors-wrapper {
    grid-template-columns: 1fr;
  }
}
.status-tag-wrapper {
  display: flex;
  align-items: center;
  height: 56px;
}

.actor-item {
  background-color: #f8f9fa;
  border-radius: 8px;
  transition: all 0.3s ease;
  padding: 20px !important;
  border: 1px solid #e4e7ed !important;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.actor-item:hover {
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
  border-color: #c0c4cc !important;
}

.actor-item h4 {
  color: #303133;
  font-size: 16px;
  margin: 0;
}

.actor-form-grid {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}

.actor-form-item {
  width: 100%;
}

.actor-form-item :deep(.el-form-item) {
  margin-bottom: 12px;
}

.actor-form-item :deep(.el-form-item__label) {
  font-weight: 500;
  font-size: 15px;
  padding-bottom: 6px;
}

.delete-actor-btn {
  padding: 5px;
  font-size: 12px;
  height: 28px;
  width: 28px;
}

.delete-actor-btn:hover {
  background-color: #f56c6c;
  color: #fff;
}

.add-actor-btn {
  font-weight: 500;
  margin-top: 16px;
  display: block;
  width: fit-content;
}

.storyboard-item-dialog {
  max-width: 1200px;
}

.storyboard-item-dialog :deep(.el-dialog__header) {
  padding: 20px 24px;
  margin-right: 0;
  border-bottom: 1px solid #ebeef5;
}

.storyboard-item-dialog :deep(.el-dialog__body) {
  padding: 24px 30px;
}

.storyboard-item-dialog :deep(.el-dialog__title) {
  font-weight: 600;
  font-size: 18px;
}

.form-content {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.form-content :deep(.el-form-item) {
  margin-bottom: 20px;
}

.form-content :deep(.el-form-item__label) {
  font-weight: 500;
  font-size: 15px;
  padding-bottom: 6px;
}

.actors-container {
  width: 100%;
}

.actors-container :deep(.el-form-item__content) {
  width: 100%;
}

.actors-wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 25px;
  margin-bottom: 20px;
  width: 100%;
}

.actor-item {
  background-color: #f8f9fa;
  border-radius: 8px;
  transition: all 0.3s ease;
  padding: 20px !important;
  border: 1px solid #e4e7ed !important;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.actor-item:hover {
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
  border-color: #c0c4cc !important;
}

.actor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  border-bottom: 1px solid #ebeef5;
  padding-bottom: 8px;
}

.actor-title {
  color: #303133;
  font-size: 15px;
  font-weight: 500;
  margin: 0;
}

.actor-preview {
  margin-top: 15px;
  border-top: 1px dashed #e4e7ed;
  padding-top: 12px;
}

.preview-title {
  font-size: 14px;
  color: #606266;
  margin-bottom: 10px;
  font-weight: 500;
}

.preview-image-container {
  width: 100%;
  height: 140px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #f5f7fa;
  border-radius: 4px;
  overflow: hidden;
}

.preview-image {
  max-width: 100%;
  max-height: 140px;
  object-fit: contain;
}

.empty-preview {
  opacity: 0.7;
}

.preview-empty {
  width: 100%;
  height: 140px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #f5f7fa;
  border-radius: 4px;
  color: #909399;
  font-size: 14px;
}

/* 图片预览样式 */
.image-preview-dialog :deep(.el-dialog__body) {
  padding: 0;
}

.image-preview-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.image-preview-wrapper {
  position: relative;
  height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #000;
  margin-bottom: 16px;
  overflow: hidden;
}

.image-zoom-container {
  position: relative;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.2s ease;
  transform-origin: center;
}

.preview-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.image-nav-buttons {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20px;
}

.image-nav-buttons button {
  pointer-events: auto;
  opacity: 0.7;
  transition: opacity 0.3s;
}

.image-nav-buttons button:hover {
  opacity: 1;
}

.image-thumbnails {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
}

.image-thumbnail {
  flex: 0 0 100px;
  cursor: pointer;
  border: 2px solid transparent;
  border-radius: 4px;
  padding: 2px;
  transition: all 0.2s;
}


.image-thumbnail:hover {
  transform: translateY(-2px);
}

.image-thumbnail img {
  width: 100%;
  height: 60px;
  object-fit: cover;
  border-radius: 2px;
}

.image-info {
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
}

.keyboard-shortcuts {
  margin-top: 10px;
  padding: 8px;
  background-color: rgba(0, 0, 0, 0.03);
  border-radius: 4px;
}

.shortcuts-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-top: 4px;
}

.shortcuts-grid div {
  display: flex;
  align-items: center;
  font-size: 12px;
  color: #606266;
}

kbd {
  background-color: #eee;
  border-radius: 3px;
  border: 1px solid #b4b4b4;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 2px 0 0 rgba(255, 255, 255, 0.7) inset;
  color: #333;
  display: inline-block;
  font-size: 0.85em;
  font-weight: 700;
  line-height: 1;
  padding: 2px 4px;
  margin-right: 4px;
  white-space: nowrap;
}

.zoom-controls {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  background-color: rgba(0, 0, 0, 0.5);
  padding: 8px 16px;
  border-radius: 20px;
  z-index: 10;
}

.zoom-controls button {
  opacity: 0.8;
  transition: opacity 0.2s;
  color: white;
  border: none;
}

.zoom-controls button:hover {
  opacity: 1;
  background-color: rgba(255, 255, 255, 0.2);
}

.zoom-reset-button {
  background-color: transparent;
  min-width: 60px;
}

.zoom-button {
  background-color: transparent;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}

.dialog-footer .el-button {
  min-width: 100px;
  margin-left: 16px;
}

.storyboard-item-dialog :deep(.el-dialog__footer) {
  padding-top: 0;
  padding-bottom: 24px;
}

.storyboard-description {
  border-left: 4px solid var(--el-color-primary-light-5);
  background-color: #f8f9fa;
  transition: all 0.3s ease;
}

.storyboard-description:hover {
  background-color: #f0f2f5;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.storyboard-description.video-prompt {
  border-left: 4px solid var(--el-color-success-light-5);
}

.storyboard-description.video-prompt:hover {
  background-color: #f0f8f0;
}

.empty-gallery-container {
  background-color: #f8f9fa;
  border-radius: 8px;
  padding: 20px;
  min-height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.loading-container {
  padding: 20px;
  background-color: #f8f9fa;
  border-radius: 8px;
  margin-bottom: 20px;
}

.loading-icon {
  font-size: 24px;
  color: var(--el-color-primary);
  margin-bottom: 16px;
  animation: rotating 2s linear infinite;
}

.loading-text {
  font-size: 16px;
  color: #606266;
  margin-bottom: 20px;
}

.polling-progress {
  width: 200px;
  height: 8px;
  background-color: #e4e7ed;
  border-radius: 4px;
  overflow: hidden;
}

.polling-bar {
  height: 100%;
  background-color: var(--el-color-primary);
  border-radius: 4px;
  transition: width 0.3s ease;
}

.polling-status {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 30px 0;
}

/* 状态标签样式 */
.status-tag {
  width: 48px;
  height: 24px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
}

.status-pending {
  background: #E8EAFC;
  color: #3644E0;
}

.status-generating {
  background: #FFF3E7;
  color: #FC860F;
}

.status-completed {
  background: #E6F9F1;
  color: #009249;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 186px;
  background-color: #f8f9fa;
  border-radius: 8px;
  margin-bottom: 20px;
}

.empty-image {
  width: 240px;
  height: 240px;
  margin-bottom: 20px;
}

.empty-text {
  font-size: 14px;
  color: #787C8F;
  margin: 20px 0;
  text-align: center;
}

.storyboard-page {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.storyboard-header {
  background-color: #fff;
  border-radius: 8px;
  padding: 20px;
  width: 80%;
  max-width: 1200px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.storyboard-header-left {
  display: flex;
  align-items: center;
}

.back-button {
  margin-right: 20px;
}

.episode-title {
  font-size: 18px;
  font-weight: 600;
}

.storyboard-progress {
  display: flex;
  align-items: center;
}

.progress-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-right: 20px;
}

.progress-circle {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: #f0f0f0;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 5px;
}

.progress-text {
  font-size: 14px;
  color: #606266;
}

.progress-line {
  height: 2px;
  background-color: #e4e7ed;
  flex-grow: 1;
}

.storyboard-header-right {
  display: flex;
  align-items: center;
}

.storyboard-content {
  background-color: #fff;
  border-radius: 8px;
  padding: 20px;
  width: 80%;
  max-width: 1200px;
  display: flex;
}

.script-area {
  flex: 1;
  margin-right: 20px;
}

.script-title {
  font-size: 18px;
  font-weight: 600;
  margin-bottom: 10px;
}

.script-content {
  font-size: 14px;
  color: #606266;
}

.storyboard-list-area {
  flex: 1;
}

.storyboard-list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.storyboard-list-title {
  font-size: 18px;
  font-weight: 600;
}

.storyboard-cards {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.storyboard-card {
  background-color: #fff;
  border-radius: 8px;
  padding: 10px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.storyboard-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.storyboard-card-title {
  font-size: 16px;
  font-weight: 600;
}

.delete-button {
  color: #3644E0;
  font-size: 14px;
}

.form-item {
  margin-bottom: 10px;
}

.form-label {
  font-weight: 500;
  font-size: 14px;
  margin-bottom: 5px;
}

.form-grid {
  display: flex;
  gap: 10px;
}

.form-column {
  flex: 1;
}

.actors-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.actor-item {
  background-color: #f8f9fa;
  border-radius: 8px;
  padding: 10px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.actor-item:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}

.scene-description {
  font-size: 14px;
  color: #606266;
  margin-bottom: 10px;
}

.scene-preview {
  margin-bottom: 10px;
}

.scene-image {
  width: 100%;
  height: 140px;
  object-fit: cover;
  border-radius: 4px;
}

.scene-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.divider {
  width: 100%;
  height: 1px;
  background-color: #e4e7ed;
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}
/* 场景生成中状态样式 */
.complete-loading-content {
  text-align: center;
  padding: 40px;
  margin-top: 220px;
}

.complete-loading-icon {
  font-size: 48px;
  color: var(--primary-color, #1C1D29);
  margin-bottom: 20px;
  animation: spin 2s infinite linear;
}
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
.complete-loading-message {
  font-size: 14px;
  color: #787C8F;
  margin-bottom: 16px;
  line-height: 1.5;
}

/* 新增剧集相关样式 */
.episode-header {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 16px;
}

.add-episode-btn {
  font-weight: 500;
}

.add-episode-dialog :deep(.el-dialog__header) {
  padding: 20px 24px;
  margin-right: 0;
  border-bottom: 1px solid #ebeef5;
}

.add-episode-dialog :deep(.el-dialog__body) {
  padding: 24px 30px;
}

.add-episode-dialog :deep(.el-dialog__title) {
  font-weight: 600;
  font-size: 18px;
}

.add-episode-dialog :deep(.el-form-item__label) {
  font-weight: 500;
  font-size: 15px;
  padding-bottom: 6px;
}

</style>

